#ifndef __COMPILER_H
#define __COMPILER_H

/* conpiler types */
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)    // arm compiler 6
    #define MX_COMPILER_TYPE_AC6
#elif defined(__GNUC__)                                         // gcc compiler
    #define MX_COMPILER_TYPE_GCC
#else                                                           // unknown compiler
    # error please choose a compiler tool chain.
#endif

/* volatile */
#define mx_io volatile

/* inline */
#define mx_inline inline

/* weak */
#if defined(MX_COMPILER_TYPE_AC6) || defined(MX_COMPILER_TYPE_GCC)
    #define mx_weak __attribute((weak))
#else
    #warning mx_weak is not supported.
#endif

/* align the variable address */
#if defined(MX_COMPILER_TYPE_AC6) || defined(MX_COMPILER_TYPE_GCC)
    #define mx_align(n) __attribute__((aligned(n)))
#else
    #warning mx_align is not supported.
#endif
#if defined(mx_align)
    #define mx_align_cpu mx_align(MX_CPU_BITWIDE_BYTE)
#endif

/* mark a variable or function as used that the compiler won't optimize it */
#if defined(MX_COMPILER_TYPE_AC6) || defined(MX_COMPILER_TYPE_GCC)
    #define mx_used __attribute((used))
#else
    #warning mx_used is not supported.
#endif

/* puts the variable or function in the specified section */
#if defined(MX_COMPILER_TYPE_AC6) || defined(MX_COMPILER_TYPE_GCC)
    #define mx_section(name) __attribute((section(name)))
#else
    #error mx_section is not supported.
#endif

/* packed, align control in struct */
#if defined(MX_COMPILER_TYPE_AC6) || defined(MX_COMPILER_TYPE_GCC)
    #define mx_packed __attribute((packed))
#else
    #error mx_packed is not supported.
#endif

/* typeof(x), get the type of variable */
#if defined(MX_COMPILER_TYPE_AC6)
    #define mx_typeof(x) __typeof__(x)
#elif defined(MX_COMPILER_TYPE_GCC)
    #define mx_typeof(x) typeof(x)
#else
    #error mx_typeof(x) is not supported.
#endif

#endif
